﻿
/**
 * nPnP - neither Perl not PHP
 *
 * Copyright (C) 2009 Christian Moeller
 *
 * This program is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation; either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; 
 * if not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FParser.Executor;
using System.IO;

namespace FParser.Runtime.Libraries
{
    public class Lib_StdIO : IBaseLibrary
    {
        public Lib_StdIO() {
            this.streams = new Dictionary<string, StreamWriter>(); 
 
        }

        public ExternalLibraryCall[] Exports {
            get
            {
                return new ExternalLibraryCall[] { 
                  echo,    
                  readLine,
                  strlen,
                  fremove,
                  fopen,
                  fwrite,
                  fclose,
                  fgeta,
                  echo_r
                };
            }
        }

        public ExecutionResult ord(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1))
            {
                string data = scope.GetParameter(1);
            }
            Console.WriteLine("\n");
            return exeResult;
        }

        private Dictionary<string, StreamWriter> streams;

        public ExecutionResult echo_r(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1))
            {
                string indent = "\n";
                _echo_r_internal(scope.Types["1"], indent, scope);
            }
            Console.WriteLine("\n");
            return exeResult;
        }

        private void _echo_r_internal(BaseType type, string indent, RuntimeScope scope)
        {
            Console.Write(indent + "[" + type.Name + "] => " + Executor.Executor.CastToValue(type, scope));
            foreach (BaseType sub in type.ObjTypes.Values)
            {
                _echo_r_internal(sub, indent + "\t", scope);
            }
        }

        public ExecutionResult fgeta(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1))
            {
                string fName = scope.GetParameter(1);

                if (File.Exists(fName))
                {
                    StreamReader stream = new StreamReader(fName);
                    exeResult.sValue = Executor.Executor.GetAnonymousType(stream.ReadToEnd());
                    stream.Close();
                    return exeResult;
                }
            }

            exeResult.sValue = Executor.Executor.GetAnonymousType("0");
            return exeResult;
        }

        public ExecutionResult fclose(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1))
            {
                string fName = scope.GetParameter(1);
                
                if (this.streams.ContainsKey(fName))
                {
                    StreamWriter stream = this.streams[fName];
                    stream.Flush();
                    stream.Close();
                }

                exeResult.sValue = Executor.Executor.GetAnonymousType("1");
                return exeResult;
            }

            exeResult.sValue = Executor.Executor.GetAnonymousType("-1");
            return exeResult;
        }

        public ExecutionResult fopen(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1))
            {
                string fName = scope.GetParameter(1);
                StreamWriter stream = new StreamWriter(fName);
                this.streams.Add(fName, stream);
                exeResult.sValue = Executor.Executor.GetAnonymousType(fName);
                return exeResult;
            }

            exeResult.sValue = Executor.Executor.GetAnonymousType("0");
            return exeResult;
        }

        public ExecutionResult fwrite(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1) && scope.HasParameter(2))
            {
                string fName = scope.GetParameter(1);
                string data = scope.GetParameter(2);


                if (this.streams.ContainsKey(fName))
                {
                    StreamWriter stream = this.streams[fName];
                    stream.Write(data);
                }

                exeResult.sValue = Executor.Executor.GetAnonymousType("1");
                return exeResult;
            }

            exeResult.sValue = Executor.Executor.GetAnonymousType("0");
            return exeResult;
        }

        public ExecutionResult fremove(RuntimeScope scope)
        {
            ExecutionResult exeResult = new ExecutionResult();

            if (scope.HasParameter(1))
            {
                string fName = scope.GetParameter(1);
                if (File.Exists(fName))
                {
                    File.Delete(fName);
                    exeResult.sValue = Executor.Executor.GetAnonymousType("1");
                    return exeResult;
                }
            }

            exeResult.sValue = Executor.Executor.GetAnonymousType("0");
            return exeResult;
        }

 

        public ExecutionResult echo(RuntimeScope scope)
        {
            string  retVal = "",
                    sOutCache;
            foreach (string key in scope.Types.Cache.Keys)
            {
                if (scope.Types.Cache[key].ObjTypes.Count > 0)
                {
                    sOutCache = "Array()";
                }
                else
                {
                    sOutCache = scope.Types[key].Value.ToString();
                    sOutCache = sOutCache.Replace("\\n", Environment.NewLine);
                    retVal += sOutCache;
                    Console.Write(sOutCache);
                }
            }
            
            ExecutionResult exeResult = new ExecutionResult();
            exeResult.sValue = Executor.Executor.GetAnonymousType(retVal);
            return exeResult;
            
        }

        public ExecutionResult readLine(RuntimeScope scope)
        {
            echo(scope);
            string sInCache = Console.ReadLine();
            ExecutionResult exeResult = new ExecutionResult();
            exeResult.sValue = Executor.Executor.GetAnonymousType(sInCache);
            return exeResult;
        }

        public ExecutionResult strlen(RuntimeScope scope)
        {
            if (scope.HasParameter(1))
            {
                ExecutionResult exeResult = new ExecutionResult();
                exeResult.sValue = Executor.Executor.GetAnonymousType(
                        scope.GetParameter(1).Length.ToString());
                return exeResult;
            }
            return null;
        }
    }
}
